package com.tim.source.templete;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.PrintWriter;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;

import com.tim.source.BaseConst;
import com.tim.source.MakeSource;
import com.tim.source.common.CommonInfo;
import com.tim.source.common.FieldInfo;
import com.tim.source.common.TableInfo;
import com.tim.source.db.DataTypeProc;
import com.tim.source.util.StringUtil;

public class HbmXmlProc {
	// hbm头部模板
	private static String headHbm;
	// hbm主键模板
	private static String idHbm;
	// hbm属性模板
	private static String contentHbm;
	// hbm尾部模板
	private static String footHbm = null;
	static {
		// 加载hbm头部模板
		headHbm = getPartString("head");
		// 替换文件作者
		headHbm = headHbm.replace("%author%", CommonInfo.AUTHOR);
		// 替换文件创建时间
		headHbm = headHbm.replace("%dateTime%", CommonInfo.DATESTRING);
		
		// 加载hbm主键模板
		idHbm = getPartString("id");

		// 加载hbm属性模板
		contentHbm = getPartString("content");

		// 加载hbm尾部模板
		footHbm = getPartString("foot");
	}

	private static String getPartString(String partStr) {
		try {
			// 加载hbm尾部模板
			InputStream part = HbmXmlProc.class.getResourceAsStream(partStr
					+ ".hbm.xml.tmp");
			byte[] partData = new byte[part.available()];
			part.read(partData);
			return new String(partData, "UTF-8");
		} catch (Exception ex) {
			ex.printStackTrace();
			return null;
		}
	}

	/**
	 * 获取hbm尾部信息.
	 */
	public static String getFootString() {
		return HbmXmlProc.footHbm;
	}

	/**
	 * 依据传入信息返回Property配置信息.
	 * 
	 * @param colName
	 *            列名.
	 * @param dataType
	 *            sql数据类型.
	 * @param length
	 *            数据长度.
	 * @param isNull
	 *            是否为空.
	 * @return Property配置信息.
	 */
	public static String getPropertyString(FieldInfo fieldInfo) {
		String buffer = new String(contentHbm);
		// 获取数据库列数据类型
		String fullDataType = fieldInfo.getDbDataType();
		// 获取对应java数据类型
		DataTypeProc typeProc = new DataTypeProc();
		fullDataType = typeProc.getDataType(MakeSource.DB_TYPE, fullDataType);
		// 设置列对应java完整类名
		fieldInfo.setFullDataType(fullDataType);
		// 获取对应java类
		int index = fullDataType.lastIndexOf(".");
		if (index != -1) {
			// 替换数据类型
			buffer = buffer.replace("%dataType%", fullDataType);
			fullDataType = fullDataType.substring(index+1);
		} else {
			buffer = buffer.replace("%dataType%", "java.lang." + fullDataType);
		}
		// 设置数据库列对应java数据类型
		fieldInfo.setDataType(fullDataType);
		// 获取数据库对应长度 
		String dbLength = fieldInfo.getDbLength();
		// 替换长度
		if (DataTypeProc.isNoLengthList(fullDataType)) {
			fieldInfo.setDataLength(0);
			buffer = buffer.replace(" length=\"%length%\"", "");
		} else {
			fieldInfo.setDataLength(Integer.parseInt(dbLength));
			buffer = buffer.replace("%length%", dbLength + "");
		}
		// 替换列名
		buffer = buffer.replaceAll("%colName%", fieldInfo.getColName());
		String isNull = fieldInfo.getIsNull();
		if ("0".equals(isNull)) {
			isNull = "true";
		} else if ("1".equals(isNull)) {
			isNull = "false";
		}
		// 替换是否空
		buffer = buffer.replace("%isNull%", isNull);
		// 替换属性名
		buffer = buffer.replace("%propName%", fieldInfo.getPropName());
		return buffer;
	}
	
	public static String getIdContent(FieldInfo fieldInfo) {
		String buffer = new String(idHbm);
		// 获取数据库列数据类型
		String fullDataType = fieldInfo.getDbDataType();
		// 获取对应java数据类型
		DataTypeProc typeProc = new DataTypeProc();
		fullDataType = typeProc.getDataType(MakeSource.DB_TYPE, fullDataType);
		// 设置列对应java完整类名
		fieldInfo.setFullDataType(fullDataType);
		String langString = "";
		// 获取对应java类
		int index = fullDataType.lastIndexOf(".");
		if (index != -1) {
			fullDataType = fullDataType.substring(index+1);
		} else {
			langString = "java.lang.";
		}
		// 设置数据库列对应java数据类型
		fieldInfo.setDataType(fullDataType);
		// 替换数据类型
		buffer = buffer.replace("%dataType%", langString + fullDataType);
		// 替换列名
		buffer = buffer.replaceAll("%colName%", fieldInfo.getColName());
		// 替换属性名
		buffer = buffer.replace("%propName%", fieldInfo.getPropName());
		return buffer;
	}

	/**
	 * 获取hbm头部信息.
	 * 
	 * @param packageStr
	 *            包路径.
	 * @param tableName
	 *            数据库表名.
	 * @return String hbm头部信息.
	 */
	public static String getHeadString(String tableName) {
		// 替换数据库表名
		String headStr = HbmXmlProc.headHbm.replace(BaseConst.TABLE_NAME,
				tableName);
		// 设置当前表对应类名称
		TableInfo.className = StringUtil.getClassName(tableName);
		// 设置当前表对应完整类名称
		String packageStr = MakeSource.ENTITY.replace("/", ".");
		TableInfo.fullClassName = packageStr + TableInfo.className;
		headStr = headStr.replace(BaseConst.CLASS, TableInfo.fullClassName);
		return headStr;
	}

	/**
	 * dom对象转化Xml.
	 * 
	 * @param document
	 *            Document.
	 * @param charset
	 *            字符集.
	 * @param fileName
	 *            保存文件路径.
	 * @return boolean
	 */
	public static boolean docToXmlFile(Document document, String charset,
			String fileName) {
		try {
			TransformerFactory tf = TransformerFactory.newInstance();
			Transformer transformer = tf.newTransformer();
			transformer.setOutputProperty(OutputKeys.ENCODING, charset);
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
			DOMSource source = new DOMSource(document);
			File file = new File(fileName);
			file.createNewFile();
			PrintWriter writer = new PrintWriter(new FileOutputStream(fileName));
			StreamResult result = new StreamResult(writer);
			transformer.transform(source, result);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}
}
